using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;

namespace SpellCore
{
    internal class Utf8Marshaller :IDisposable
    {
        public Utf8Marshaller (string value)
	    {
            byte[] bytes = new byte[Encoding.UTF8.GetByteCount(value) + 1];
            int bytesWritten = Encoding.UTF8.GetBytes(value, 0, value.Length, bytes, 0);
            bytes[bytesWritten] = 0; // null terminate it
            ++bytesWritten;
            MarshalledValue = Marshal.AllocHGlobal(bytesWritten);
            for (int i = 0; i < bytes.Length; i++)
            {
                Marshal.WriteByte(MarshalledValue, i, bytes[i]);

            }
	    }

        private IntPtr _unmanagedPrt;
        public IntPtr MarshalledValue
        {
            get { return _unmanagedPrt; }
            protected set { _unmanagedPrt = value; }
        }

    
        public static List<string> MarshalFromUtf8Array(IntPtr listAddress, int count)
        {
            List<string> strings = new List<string>();

            for (int i = 0; i < count; i++)
            {
                IntPtr stringAddress = Marshal.ReadIntPtr(listAddress, i * IntPtr.Size);
                string s = MarshalFromUtf8(stringAddress);
                strings.Add(s);

            }
            return strings;

        }

        public static string MarshalFromUtf8(IntPtr intPtr)
        {
            if(intPtr.ToInt64() == 0)
            {
                return null;
            }
            List<byte> bytes = new List<byte>();
            for (int i = 0; true; i++)
            {
                byte b = Marshal.ReadByte(intPtr, i);
                if (b == 0)
                {
                    break;
                }
                bytes.Add(b);
            }
            return Encoding.UTF8.GetString(bytes.ToArray());
        }
        
        
        ~Utf8Marshaller()
        {
            Dispose(false);
        }



        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        private bool _isDisposed;
        private void Dispose(bool disposing)
        {
            if (_isDisposed)
                return;
            _isDisposed = true;
            if (disposing)
            {
                //dump managed resources
            }

            Marshal.FreeHGlobal(MarshalledValue);
        }
    }
}
